#include "config.h"
#include "utils.h"

#include "yyjson/yyjson.h"

int loadServerConfig(const char *file_path, ServerConfig_t *config)
{
    FILE *fp = fopen(file_path, "r");
    if (!fp) {
        fprintf(stderr, "error: cannot open file %s\n", file_path);
        return -1;
    }
    fseek(fp, 0, SEEK_END);
    size_t file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *file_content = (char *)malloc(file_size + 1);
    if (!file_content) {
        fprintf(stderr, "error: cannot allocate memory\n");
        fclose(fp);
        return -1;
    }
    fread(file_content, 1, file_size, fp);
    file_content[file_size] = '\0';
    fclose(fp);

    yyjson_doc *doc = yyjson_read(file_content, file_size, 0);
    free(file_content);
    if (!doc) {
        fprintf(stderr, "error: cannot parse JSON\n");
        return -1;
    }

    yyjson_val *root = yyjson_doc_get_root(doc);
    if (!yyjson_is_obj(root)) {
        fprintf(stderr, "error: invalid JSON format\n");
        yyjson_doc_free(doc);
        return -1;
    }

    yyjson_val *ip = yyjson_obj_get(root, "ip");
    yyjson_val *port = yyjson_obj_get(root, "port");
    yyjson_val *max_connections = yyjson_obj_get(root, "max_connections");
    yyjson_val *thread_pool_size = yyjson_obj_get(root, "thread_pool_size");
    yyjson_val *task_queue_size = yyjson_obj_get(root, "task_queue_size");
    yyjson_val *log_path = yyjson_obj_get(root, "log_path");
    yyjson_val *storage_path = yyjson_obj_get(root, "storage_path");
    yyjson_val *mysql = yyjson_obj_get(root, "mysql");
    yyjson_val *tunnel_count = yyjson_obj_get(root, "tunnel_count");
    yyjson_val *tunnel_list = yyjson_obj_get(root, "tunnel_list");

    if (!yyjson_is_str(ip) || !yyjson_is_num(port) || 
        !yyjson_is_num(max_connections) || !yyjson_is_num(thread_pool_size) || 
        !yyjson_is_num(task_queue_size) || !yyjson_is_str(log_path) || 
        !yyjson_is_str(storage_path) || !yyjson_is_obj(mysql) || 
        !yyjson_is_num(tunnel_count) || !yyjson_is_obj(tunnel_list)) {
        fprintf(stderr, "error: invalid config format\n");
        yyjson_doc_free(doc);
        return -1;
    }

    strcpy(config->ip, yyjson_get_str(ip));
    config->port = (int)yyjson_get_num(port);
    config->max_connections = (int)yyjson_get_num(max_connections);
    config->thread_pool_size = (int)yyjson_get_num(thread_pool_size);
    config->task_queue_size = (int)yyjson_get_num(task_queue_size);
    strcpy(config->log_path, yyjson_get_str(log_path));
    strcpy(config->storage_path, yyjson_get_str(storage_path));

    yyjson_val *mysql_host = yyjson_obj_get(mysql, "host");
    yyjson_val *mysql_port = yyjson_obj_get(mysql, "port");
    yyjson_val *mysql_db = yyjson_obj_get(mysql, "db");
    yyjson_val *mysql_user = yyjson_obj_get(mysql, "user");
    yyjson_val *mysql_password = yyjson_obj_get(mysql, "password");

    if (!yyjson_is_str(mysql_host) || !yyjson_is_num(mysql_port) || 
        !yyjson_is_str(mysql_db) || !yyjson_is_str(mysql_user) || 
        !yyjson_is_str(mysql_password)) {
        fprintf(stderr, "error: invalid MySQL config format\n");
        yyjson_doc_free(doc);
        return -1;
    }

    strcpy(config->mysql_host, yyjson_get_str(mysql_host));
    config->mysql_port = (int)yyjson_get_num(mysql_port);
    strcpy(config->mysql_db, yyjson_get_str(mysql_db));
    strcpy(config->mysql_user, yyjson_get_str(mysql_user));
    strcpy(config->mysql_password, yyjson_get_str(mysql_password));

    config->tunnel_count = (int)yyjson_get_num(tunnel_count);
    if (config->tunnel_count > MAX_TUNNELS) {
        fprintf(stderr, "error: too many tunnels\n");
        yyjson_doc_free(doc);
        return -1;
    }

    for (int i = 0; i < config->tunnel_count; i++) {
        char tunnel_key[16];
        snprintf(tunnel_key, sizeof(tunnel_key), "tunnel_%d", i + 1);
        yyjson_val *tunnel = yyjson_obj_get(tunnel_list, tunnel_key);
        if (!tunnel) {
            fprintf(stderr, "error: missing tunnel key %s\n", tunnel_key);
            yyjson_doc_free(doc);
            return -1;
        }
        
        yyjson_val *tunnel_ip = yyjson_obj_get(tunnel, "ip");
        yyjson_val *tunnel_port = yyjson_obj_get(tunnel, "port");
        
        if (!yyjson_is_str(tunnel_ip) || !yyjson_is_num(tunnel_port)) {
            fprintf(stderr, "error: invalid tunnel format\n");
            yyjson_doc_free(doc);
            return -1;
        }

        strcpy(config->tunnels[i].ip, yyjson_get_str(tunnel_ip));
        config->tunnels[i].port = (int)yyjson_get_num(tunnel_port);
    }

    yyjson_doc_free(doc);
    return 0;
}

